MEGpipeline_NormMRI_Guts.m 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. % Normalises MRI and volumes via Fieldtrip and SPM. %
  3. % Last modified: Jan. 15, 2014 %
  4. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5. %
  6. % Usage:
  7. % [NormMRI, NormParams] = MEGpipeline_NormMRI_Guts...
  8. % (FTcfg, SPMcfg, MRIdata, Res, OutpathNormMRI)
  9. %
  10. % Inputs:
  11. % Note: FTcfg & SPMcfg can be generated & imported from a Builder .mat file.
  12. % FTcfg.WriteNormMRI = Fieldtrip config for ft_volumewrite.
  13. % SPMcfg.Estimate = SPM config estimate field from spm_get_defaults.
  14. % SPMcfg.Write = SPM config write field from spm_get_defaults.
  15. %
  16. % MRIdata = Loaded FT structure containing MRI anatomy OR path to FT .mat MRIdata file.
  17. % Res = Desired resolution (in mm) of output normalised MRI.
  18. % OutpathNormMRI = Output /path/filename of normalised MRI.
  19. % Copyright (C) 2013-2014, Michael J. Cheung
  20. %
  21. % This file is a part of the MEG & PLS Pipeline (MEGPLS). For more
  22. % details, see the documentation included with the software package.
  23. %
  24. % MEGPLS is free software: you can redistribute it and/or modify it under
  25. % the terms of the GNU General Public License version 2 as published by
  26. % the Free Software Foundation. This program is distributed in the hope
  27. % that it will be useful, but WITHOUT ANY WARRANTY; without even the
  28. % implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  29. % See the GNU General Public License for more details.
  30. %
  31. % You should have received a copy of the GNU General Public License along
  32. % with this program. If not, you can download the license here:
  33. % <http://www.gnu.org/licenses/old-licenses/gpl-2.0>.
  34. function [NormMRI, NormParams] = MEGpipeline_NormMRI_Guts...
  35. (MainFTcfg, MainSPMcfg, MRIdata, Res, OutpathNormMRI)
  36. NormMRI = []; % Initialize output variables
  37. NormParams = [];
  38. % Check number of input & output arguments:
  39. if nargin ~= 5
  40. error('ERROR: Incorrect number of input arguments. See help for usage info.')
  41. end
  42. if nargout > 2
  43. error('ERROR: Incorrect number of output arguments. See help for usage info.')
  44. end
  45. % Load settings and check MRI:
  46. SPMcfg.Estimate = MainSPMcfg.Estimate;
  47. SPMcfg.Write = MainSPMcfg.Write;
  48. SPMcfg.Write.vox = [Res, Res, Res];
  49. %==========================%
  50. % BEGIN MRI NORMALISATION: %
  51. %==========================%
  52. % If MRIdata is path to FT .mat, load it:
  53. if ~isstruct(MRIdata)
  54. MRIdata = LoadFTmat(MRIdata, 'NormaliseSPM');
  55. if isempty(MRIdata)
  56. return;
  57. end
  58. end
  59. % Convert MRI into approximate RAS-orientation (SPM space):
  60. % Keep initial transformation matrix (To emulate "ft_volumenormalise").
  61. MRIdata = ft_checkdata(MRIdata, 'datatype', 'volume', 'feedback', 'yes');
  62. MRIdata = ft_convert_units(MRIdata, 'mm');
  63. orig = MRIdata.transform;
  64. MRIdata = ft_convert_coordsys(MRIdata, 'spm');
  65. initial = MRIdata.transform / orig;
  66. % Write volume fields to NIFTI:
  67. [FolderNormMRI, NameNormMRI, ~] = fileparts(OutpathNormMRI);
  68. disp('Writing MRI volume fields to NIFTI for SPM:')
  69. VolumeFields = parameterselection('all', MRIdata); % Get volume fields
  70. for f = 1:length(VolumeFields)
  71. TempFilename{f} = [VolumeFields{f},'_',NameNormMRI];
  72. TempFilename{f}(strfind(TempFilename{f}, '.')) = []; % ft_volumewrite cannot read dots.
  73. if strcmp(VolumeFields{f}, 'anatomy')
  74. TempAnatFile = [TempFilename{f},'.nii'];
  75. end
  76. FTcfg.WriteNormMRI = [];
  77. FTcfg.WriteNormMRI = MainFTcfg.WriteNormMRI;
  78. FTcfg.WriteNormMRI.parameter = VolumeFields{f};
  79. FTcfg.WriteNormMRI.filename = TempFilename{f};
  80. FTcfg.WriteNormMRI.filetype = 'nifti';
  81. ft_volumewrite(FTcfg.WriteNormMRI, MRIdata)
  82. end
  83. MRIdata = []; % Free memory
  84. % Normalise anatomy volume and get parameters:
  85. Template = [spm('dir'),'/templates/T1.nii'];
  86. disp('Normalising anatomy:')
  87. NormParams = spm_normalise(Template, TempAnatFile, [], [], [], SPMcfg.Estimate);
  88. spm_write_sn(TempAnatFile, NormParams, SPMcfg.Write);
  89. % To emulate "ft_volumenormalise:"
  90. % Determine the affine source -> template coordinate transformation:
  91. TemplateHdr = spm_vol(Template);
  92. AnatHdr = spm_vol(TempAnatFile);
  93. Final = TemplateHdr.mat * inv(NormParams.Affine) * inv(AnatHdr.mat) * initial;
  94. TemplateHdr = []; % Free memory
  95. AnatHdr = [];
  96. % Read normalised anatomy back into FT:
  97. NormMRI = ft_read_mri(['w',TempAnatFile]);
  98. NormMRI.params = NormParams;
  99. NormMRI.initial = initial;
  100. NormMRI.coordsys = 'spm';
  101. NormMRI.unit = 'mm';
  102. NormMRI.cfg.final = Final;
  103. NormMRI.cfg.spmparams = NormParams;
  104. system(['rm ',TempAnatFile]); % Remove remnant volume field files.
  105. system(['rm w',TempAnatFile]);
  106. Final = []; % Free memory
  107. % Normalise other volume fields and read back into FT:
  108. disp('Apply normalisation to other fields:')
  109. for f = 1:length(VolumeFields)
  110. if strcmp(VolumeFields{f}, 'anatomy')
  111. continue; % anatomy already done
  112. end
  113. TempFile = [TempFilename{f},'.nii'];
  114. spm_write_sn(TempFile, NormParams, SPMcfg.Write);
  115. hdr = spm_vol_nifti(['w',TempFile]);
  116. img = spm_read_vols(hdr);
  117. NormMRI = setsubfield(NormMRI, VolumeFields{f}, img);
  118. system(['rm ',TempFile]); % Remove remnant volume field files.
  119. system(['rm w',TempFile]);
  120. hdr = []; % Free memory
  121. img = [];
  122. end
  123. if isfield(NormMRI, 'inside') % Convert inside back to logical
  124. NormMRI.inside = abs(NormMRI.inside-1)<=10*eps;
  125. end
  126. % Align volume (voxel-space) with headcoordinate axes (SPM world-space):
  127. % Note: Yields identical results as loading & saving with NIFTImatlab.
  128. NormMRI = align_ijk2xyz(NormMRI);
  129. % Save NormMRI:
  130. CheckSavePath(OutpathNormMRI, 'NormaliseSPM');
  131. save(OutpathNormMRI, 'NormMRI');